﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using FarseerGames.FarseerPhysics;
using FarseerGames.FarseerPhysics.Mathematics;
using FarseerGames.FarseerPhysics.Dynamics;
using FarseerGames.FarseerPhysics.Collisions;

namespace Demo3
{
  public partial class Page : UserControl
  {
    private Storyboard gameLoop;
    private PhysicsSimulator physicsSimulator;
    private KeyHandler keyHandler;

    //The entity you can control via the keyboard
    private PhysicsBox playerBox;

    //Values used to move the playerBox around
    protected float forceAmount = 50000;
    protected float torqueAmount = 500000;

    //Todo: Instead of PhysicsBox, we need a "base" class. 
    //But this will work for this "Getting Started" purpose.
    //This list holds all the "elements" in the game, that should be updated at the gameloop tick.
    private List<PhysicsBox> entityList = new List<PhysicsBox>();

    public Page()
    {
      //Default Component Initializer created by VS2008, just leave it :)
      InitializeComponent();

      this.Loaded += new RoutedEventHandler(Page_Loaded);
    }

    protected void Page_Loaded(object sender, RoutedEventArgs e)
    {
      //Setup KeyHandler - This class is taken from the original 
      //Farseer Physics Engine release 1.0.0.5 (No reason to re-invent the wheel)
      keyHandler = new KeyHandler();
      keyHandler.Attach(this);

      //Setup GameLoop
      gameLoop = new Storyboard();
      gameLoop.Completed += new EventHandler(gameLoop_Completed);
      gameLoop.Duration = TimeSpan.FromMilliseconds(15); //The game will be updated every 15 millisecond
      this.Resources.Add("gameloop", gameLoop);

      //Setup PhysicsSimulator - No gravity applied this time
      physicsSimulator = new PhysicsSimulator(new Vector2(0, 0));


      //Add our PhysicsBox (PhysicsElement, Sprite, what ever you wanna call it)
      playerBox = new PhysicsBox(100, 100, 100);
      playerBox.Body.Position = new Vector2((float)this.Width / 2, (float)this.Height / 2);

      //Setup physical appearance for the playerBox. This will set the box physical boundaries for the 
      //playerBox so the PhysicsSimulator knows how the box should behave.
      Vertices playerVertices = Vertices.CreateRectangle((float)playerBox.Width, (float)playerBox.Height);
      Geom playerGeometry = new Geom(playerBox.Body, playerVertices, Vector2.Zero, 0, 12.8f); //12.8f taken from Demo2 in Farseer. Need a fix here as I dunno what it's doing :)
      

      //Setup a dummy box to test against
      PhysicsBox dummyBox = new PhysicsBox(150, 150, 2000);
      dummyBox.Body.Position = new Vector2((float)playerBox.Body.Position.X, ((float)playerBox.Body.Position.Y - (float)dummyBox.Height));
      Vertices dummyVertices = Vertices.CreateRectangle((float)dummyBox.Width, (float)dummyBox.Height);
      Geom dummyGeometry = new Geom(dummyBox.Body, dummyVertices, Vector2.Zero, 0, 12.8f); //12.8 taken from Demo2 in Farseer. Need a fix here.


      //Add the Body of the boxes here, so it will be affected by the physicsSimulator.
      physicsSimulator.Add(playerBox.Body);
      physicsSimulator.Add(dummyBox.Body);

      //Adds the geometry for the boxes to the simulator too
      physicsSimulator.Add(playerGeometry);
      physicsSimulator.Add(dummyGeometry);
      
      //Add the actual PhysicsBox(UserControl) object to the list of UserControls to be updated in the gameloop event
      entityList.Add(playerBox);
      entityList.Add(dummyBox);

      //Finally we add the PhysicsBox (UserControl) to the actual canvas where we want it to be rendered, so we can actually see it :)
      //We also add the dummyBox, else we will never see it on the canvas
      this.DrawingCanvas.Children.Add(playerBox);
      this.DrawingCanvas.Children.Add(dummyBox);

      //This will start the actual gameloop - this is where your application actually starts (from the users point of view)
      gameLoop.Begin();
    }

    protected void gameLoop_Completed(object sender, EventArgs e)
    {
      //Update the entities from the inputs from the Keyboard
      HandleKeyboard();

      //Update the physics
      physicsSimulator.Update(.01f);

      //Update every entity in the game
      foreach (PhysicsBox box in entityList)
      {
        box.Update();
      }

      gameLoop.Begin();
    }

    private void HandleKeyboard()
    {
      Vector2 force = Vector2.Zero;
      force.Y = -force.Y;
      if (this.keyHandler.IsKeyPressed(Key.A)) { force += new Vector2(-forceAmount, 0); }
      if (this.keyHandler.IsKeyPressed(Key.S)) { force += new Vector2(0, forceAmount); }
      if (this.keyHandler.IsKeyPressed(Key.D)) { force += new Vector2(forceAmount, 0); }
      if (this.keyHandler.IsKeyPressed(Key.W)) { force += new Vector2(0, -forceAmount); }

      playerBox.Body.ApplyForce(force);

      float torque = 0;
      if (this.keyHandler.IsKeyPressed(Key.K)) { torque -= torqueAmount; }
      if (this.keyHandler.IsKeyPressed(Key.L)) { torque += torqueAmount; }
      playerBox.Body.ApplyTorque(torque);

    }
  }
}
